package com.palm.dev.service;

import com.jfinal.template.Engine;
import com.palm.core.util.StringUtil;
import com.palm.dev.common.ZdmDataTypes;
import com.palm.dev.mode.Column;
import com.palm.dev.mode.Model;
import com.palm.dev.mode.Table;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.noear.solon.annotation.Component;
import org.noear.solon.core.util.PrintUtil;

import java.io.File;
import java.io.StringReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
public class DMServices {
    private List<Model> models=new ArrayList<>();
    private Engine engine;
    private String basePath;
//    @Init
//    public void init(){
//        engine=Engine.use();
//        engine.setToClassPathSourceFactory();
//        engine.setDevMode(true);
//        engine.setBaseTemplatePath("template");
//        engine.addSharedStaticMethod(StringUtil.class);
//        basePath=DMServices.class.getClassLoader().getResource("./").getPath().replaceFirst("target/test-classes/","");
//    }
    public void importDM(String fileContent){

    }
    public void loadModels() {
        PrintUtil.info("start load models");
       URL path= DMServices.class.getClassLoader().getResource("db");
        if(path!=null){
            File dir=new File(path.getFile());
            if(dir.isDirectory()){
              for(File f:dir.listFiles()){
                  if(f.getName().endsWith(".zdm")){
                      loadModels(f);
                  }
              }
            }
        }
    }

//    private void genListView(Table table){
//        File out=new File(basePath+"src/main/resources/static/"+table.getModule()+"/"+StringUtil.firstCharToLowerCase(table.getCRUDPrefix())+".vue");
//        if(out.exists()){
//            int options=JOptionPane.showConfirmDialog(null, "ListView 代码已存在,是否覆盖？", "是否覆盖", JOptionPane.YES_NO_OPTION);
//            if(options==JOptionPane.NO_OPTION){
//                return;
//            }
//        }
//        if(!out.getParentFile().exists()){
//            out.getParentFile().mkdirs();
//        }
//        Map<String,Object> params=new HashMap<>();
//        params.put("table",table);
//        params.put("nl","\n");
//        //String out=engine.getTemplate("entity.tpl").renderToString(params);
//        engine.getTemplate("list.vue.tpl").render(params,out);
//    }
//    private void genController(Table table){
//        File out=new File(basePath+"src/main/java/"+table.getPackagePath()+"/controller/"+table.getCRUDPrefix()+"Controller.java");
//        if(out.exists()){
//          int options=JOptionPane.showConfirmDialog(null, "Controller 代码已存在,是否覆盖？", "是否覆盖", JOptionPane.YES_NO_OPTION);
//            if(options==JOptionPane.NO_OPTION){
//                return;
//            }
//        }
//        if(!out.getParentFile().exists()){
//            out.getParentFile().mkdirs();
//        }
//        Map<String,Object> params=new HashMap<>();
//        params.put("table",table);
//        params.put("nl","\n");
//        //String out=engine.getTemplate("entity.tpl").renderToString(params);
//        engine.getTemplate("controller.tpl").render(params,out);
//    }
//    private void genEntity(Table table){
//        File out=new File(basePath+"src/main/java/"+table.getPackagePath()+"/entity/"+table.getCRUDPrefix()+".java");
//        if(!out.getParentFile().exists()){
//            out.getParentFile().mkdirs();
//        }
//        Map<String,Object> params=new HashMap<>();
//        params.put("table",table);
//
//        //String out=engine.getTemplate("entity.tpl").renderToString(params);
//       engine.getTemplate("entity.tpl").render(params,out);
//    }
    private Table findTable(String path,String tableCode){
        for(Model m:models){
            if(m.getPath().equals(path)){
                for(Table tb:m.getTables()){
                    if(tableCode.equals(tb.getCode())){
                        return tb;
                    }
                }
            }
        }
        return null;
    }
    private void loadModels(File file){
        Document dom=load(file);
        Model m=new Model();
        m.setPath(file.getName());
       for(Element el: dom.getRootElement().elements()){
           String elName=el.getName();
           if("attr".equals(elName)){
              if("ModelName".equals(el.attributeValue("name"))){
                  m.setName(el.getText());
              }
           }else if("category".equals(elName)){
               loadTables(el,m.getTables(),m.getName());
           }
       }
       models.add(m);
    }
    public Model loadModel(String content){
        Document dom=load(content);
        Model m=new Model();
        for(Element el: dom.getRootElement().elements()){
            String elName=el.getName();
            if("attr".equals(elName)){
                if("ModelName".equals(el.attributeValue("name"))){
                    m.setName(el.getText());
                }
            }else if("category".equals(elName)){
                loadTables(el,m.getTables(),m.getName());
            }
        }
        return m;
    }
    private void loadTables(Element el, List<Table> tables,String modelName){
       List<Element> tableElements= el.elements("tables");
       for(Element e:tableElements){
           for(Element tb:e.elements("table")){
               Table table=loadTable(tb);
               tables.add(table);
           }
       }
    }
    private Table loadTable(Element el){
        Table table=new Table();
        Map<String,String> attrs=new HashMap<>();
        for(Element e: el.elements()){
            String elName=e.getName();
            if("attr".equals(elName)){
                attrs.put(e.attributeValue("name"),e.getText());
            }else if("columns".equals(elName)){
                loadColumns(e,table.getColumns());
            }
        }
        table.setCode(attrs.get("Code"));
        table.setName(attrs.get("CRUDPrefix"));
        table.setTitle(attrs.get("Name"));

//        String javaPath=attrs.get("CRUDJavaPath");
//        if(StringUtil.isNotEmpty(javaPath)) {
//            javaPath=javaPath.replaceFirst("JAVA/", "").replaceFirst("/ui$", "");
//        }else{
//            javaPath="";
//        }
       // table.setPackagePath(javaPath);
      //  table.setPackageName(javaPath.replaceAll("/","."));

        String uiPath=attrs.get("CRUDUIPath").replaceFirst("UI/","");
        table.setModule(uiPath);

        table.setName(attrs.get("CRUDPrefix"));
       // table.setGenerateCRUDPriv(Boolean.valueOf(attrs.get("GenerateCRUDPriv")));
       // table.setGenerateCRUD(Boolean.valueOf(attrs.get("GenerateCRUD")));
        return table;
    }
    private void loadColumns(Element columnsEl, List<Column> columns){
       for(Element columnEl:columnsEl.elements()){
               columns.add(loadColumn(columnEl));
       }
    }
    private Column loadColumn(Element column){
        Column c= new Column();
        Map<String,String> attrs=new HashMap<>();
        for(Element e: column.elements()){
            String elName=e.getName();
            if("attr".equals(elName)){
                attrs.put(e.attributeValue("name"),e.getText());
            }
        }
        c.setName(attrs.get("Name"));
        String code= StringUtil.firstCharToLowerCase(attrs.get("Code"));
        if(code.equals("iD")){
            code="id";
        }
        c.setCode(code);
        c.setControlType(attrs.get("ControlType"));
        int dataType=Integer.valueOf(attrs.get("DataType"));
        c.setDataType(ZdmDataTypes.toJavaType(dataType));
        c.setType(ZdmDataTypes.toSqlType(dataType));
        c.setMandatory(Boolean.valueOf(attrs.get("isMandatory")));
        c.setPrimaryKey(Boolean.valueOf(attrs.get("isPrimaryKey")));
        c.setSearchCondition(Boolean.valueOf(attrs.get("isSearchCondition")));
        c.setVisibleInForm(Boolean.valueOf(attrs.get("isVisiableInForm")));
        c.setVisibleInList(Boolean.valueOf(attrs.get("isVisiableInList")));
        c.setLength(Integer.valueOf(attrs.get("Length")));
        String memo=attrs.get("Memo");
        c.setMemo(memo==null?null:memo.trim());
        String options=attrs.get("Options");
        if(options!=null){
            options=options.trim();
            if(options.startsWith("CodeType:")){
                c.setOptions("dict:"+options.substring(9));
            }
        }
        //c.setOptions(options==null?null:options.trim());
        c.setPrecision(Integer.valueOf(attrs.get("Precision")));
        String verify=attrs.get("Verify");
        c.setVerify(verify==null?null:verify.trim());
        return c;
    }
    private Document load(String content){
        SAXReader reader = new SAXReader();
        try {
            Document document = reader.read(new StringReader(content));
            return document;
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        return null;
    }
    private Document load(File file) {
        SAXReader reader = new SAXReader();
        try {
            Document document = reader.read(file);
            return document;
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        return null;
    }
}
